Skip to content

fix(ci): resolve cross-platform test failures#1039

Merged
affaan-m merged 7 commits intomainfrom
fix/ci-test-failures
Mar 31, 2026
Merged

fix(ci): resolve cross-platform test failures#1039
affaan-m merged 7 commits intomainfrom
fix/ci-test-failures

Conversation

@affaan-m
Copy link
Copy Markdown
Owner

@affaan-m affaan-m commented Mar 31, 2026

Summary

  • Sanity check falls back to grep: check-codex-global-state.sh used rg (ripgrep) which is not available on GitHub Actions Ubuntu 24.04 runners. Added search_file() helper that uses rg when available, falls back to grep -En. All regex patterns converted to POSIX ERE for portability. This was the root cause of the codex-hooks sync test failing on all platforms.
  • Windows path separator in unicode test: The check-unicode-safety.test.js regex expected / separators but Windows uses \. Changed to [/\\] character class.
  • Python UTF-8 encoding in gacha test: Windows Python defaults to cp1252 encoding, which cannot encode the box-drawing characters used in gacha output. Set PYTHONUTF8=1 in the test env.
  • Skip quoted-path test on Windows: The shell injection test creates directories with " in the name, which NTFS does not allow. Test now skips on win32.

Test plan

  • All 3 affected test files pass locally
  • codex-hooks test passes without rg on PATH (simulating CI)
  • Full test suite: 1694/1696 pass (2 pre-existing failures unrelated to this PR)
  • CI should pass on ubuntu-latest, macos-latest, and windows-latest

Summary by cubic

Fixes cross-platform test failures and stabilizes CI on Ubuntu, macOS, and Windows. Adds remotion-video-creation (29 rules), restores autonomous-agent-harness and lead-intelligence, adds social-graph-ranker, updates the catalog to 140 skills, and hardens tooling with pinned MCP servers, Dependabot, and resolved npm audit vulnerabilities.

  • Bug Fixes

    • scripts/codex/check-codex-global-state.sh: added portable search_file() using rg or grep -En; converted patterns to POSIX ERE.
    • tests/scripts/check-unicode-safety.test.js: path regex accepts / or \.
    • tests/scripts/openclaw-persona-forge-gacha.test.js: set PYTHONUTF8=1 for UTF-8 stdout on Windows.
    • tests/scripts/codex-hooks.test.js: skipped quoted-path shell-injection test on Windows due to NTFS rules.
    • Remotion rule files: fixed markdownlint violations (MD047, MD012, MD034).
    • skills/lead-intelligence: replaced Unicode arrows with ASCII to satisfy CI unicode safety checks.
  • Dependencies

    • .mcp.json: pinned MCP servers for supply-chain safety (@modelcontextprotocol/server-github@2025.4.8, @modelcontextprotocol/server-memory@2026.1.26, @modelcontextprotocol/server-sequential-thinking@2025.12.18, @playwright/mcp@0.0.69).
    • .github/dependabot.yml: weekly updates for npm and github-actions with grouped minor/patch PRs.
    • .github/workflows/monthly-metrics.yml: pinned actions/github-script to a commit SHA.
    • package.json/lockfiles: upgraded markdownlint-cli to ^0.48.0, patched brace-expansion and other advisories; npm audit now reports 0 vulnerabilities; regenerated yarn.lock to match package.json.

Written for commit cbc65a8. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • Added new skills and agent workflows (lead-intelligence, autonomous-agent-harness, social-graph-ranker) and Remotion example components (bar chart, typewriter, word-highlight).
  • Documentation

    • Large Remotion rules/guides and many skill docs added; catalog counts updated (skills 136 → 140).
  • Tests

    • Improved cross-platform robustness: Windows-aware test skip, path-separator-tolerant assertions, and PYTHONUTF8 preservation in a test run.
  • Chores

    • Enhanced repository checks and scripts, manifest module path additions, dependency/workflow pins, dependabot config, and a tooling dev-dep bump.

- Sanity check script (check-codex-global-state.sh) now falls back to
  grep -E when ripgrep is not available, fixing the codex-hooks sync
  test on all CI platforms. Patterns converted to POSIX ERE for
  portability.
- Unicode safety test accepts both / and \ path separators so the
  executable-file assertion passes on Windows.
- Gacha test sets PYTHONUTF8=1 so Python uses UTF-8 stdout encoding on
  Windows instead of cp1252, preventing UnicodeEncodeError on box-drawing
  characters.
- Quoted-hook-path test skipped on Windows where NTFS disallows
  double-quote characters in filenames.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Refactors text-search in scripts/codex/check-codex-global-state.sh into a search_file helper (prefers rg, falls back to grep), tightens regexes to POSIX ERE, adds a Windows skip to a codex-hooks test, updates a unicode-safety test to accept Windows path separators, sets PYTHONUTF8=1 for a Python gacha invocation, and adds many Remotion and lead-intelligence skill docs and assets.

Changes

Cohort / File(s) Summary
Codex script refactor
scripts/codex/check-codex-global-state.sh
Introduce search_file helper using rg -n or fallback grep -En; replace direct ripgrep/grep calls; replace \s* with POSIX ERE [[:space:]]*; minor control-flow style change.
Tests — cross-platform & env
tests/scripts/check-unicode-safety.test.js, tests/scripts/codex-hooks.test.js, tests/scripts/openclaw-persona-forge-gacha.test.js
Accept both \/ and \ path separators in a stderr regex; skip a Unix-only quoted-hook-path test on Windows via os.platform(); preserve process.env and set PYTHONUTF8: '1' when launching the Python gacha script.
Manifests
manifests/install-modules.json, .mcp.json
Add skills/lead-intelligence and skills/social-graph-ranker to business-content.paths; add skills/remotion-video-creation to media-generation.paths; pin several MCP server package versions in .mcp.json.
New skills — Autonomous & Lead Intelligence
skills/autonomous-agent-harness/SKILL.md, skills/lead-intelligence/SKILL.md, skills/lead-intelligence/agents/*
Add Autonomous Agent Harness doc and lead-intelligence skill with multiple agent spec docs (enrichment-agent, mutual-mapper, outreach-drafter, signal-scorer).
New Remotion skill + rules
skills/remotion-video-creation/SKILL.md, skills/remotion-video-creation/rules/*
Add Remotion skill and many rule pages (audio, assets, charts, compositions, captions, decoding, metadata, fonts, timing, transitions, sequencing, trimming, videos, etc.).
Remotion assets / components
skills/remotion-video-creation/rules/assets/*
Add React/Remotion components (bar chart, typewriter, word-highlight) exporting MyAnimation and internal helpers.
Docs / README / AGENTS.md
AGENTS.md, README.md
Update documented skill/catalog counts from 136 → 140 (docs-only).
Repository config
.github/dependabot.yml, .github/workflows/monthly-metrics.yml, package.json
Add Dependabot configuration; pin actions/github-script to a commit SHA; bump markdownlint-cli devDependency.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐇 I hopped through grep and ripgrep lanes,
I stitched a helper to spare repeated pains.
Slashes now welcome, forward or back,
Python hums UTF‑8 along its track.
Docs bloom and demos dance — I nibble a carrot, clap!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'fix(ci): resolve cross-platform test failures' directly describes the main objective of the changeset—fixing cross-platform CI/test failures.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ci-test-failures

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 4 files

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d728312b58

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


if [[ -f "$AGENTS_FILE" ]]; then
if rg -n '^# Everything Claude Code \(ECC\) — Agent Instructions' "$AGENTS_FILE" >/dev/null 2>&1; then
if search_file '^# Everything Claude Code \(ECC\)' "$AGENTS_FILE"; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require exact ECC root heading in sanity check

The new regex ^# Everything Claude Code \(ECC\) is now prefix-only, so a truncated or altered AGENTS heading can still pass this validation. In this script’s post-sync regression role, that creates a false positive where AGENTS contains ECC root instructions is reported even when the canonical root instructions header is incomplete, which can hide a broken merge/state. Use a full-match pattern (or another strict invariant) so corrupted AGENTS content is detected reliably.

Useful? React with 👍 / 👎.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 31, 2026

Greptile Summary

This PR hardens CI cross-platform reliability by fixing three root-cause test failures (missing rg binary on Ubuntu runners, Windows path separators, and Windows Python encoding) and adds supply-chain safety improvements (pinned MCP server versions, pinned GitHub Actions SHA, Dependabot config). It also adds new skills (remotion-video-creation, lead-intelligence, autonomous-agent-harness, social-graph-ranker) and updates the catalog count.

  • scripts/codex/check-codex-global-state.sh: introduced a search_file() helper that transparently falls back from rg to grep -En; all \s shorthand patterns replaced with POSIX [[:space:]] character classes so the script is portable across any POSIX shell environment without ripgrep.
  • tests/scripts/check-unicode-safety.test.js: path-separator regex widened from / to [/\\] — correct fix for Windows stderr output.
  • tests/scripts/openclaw-persona-forge-gacha.test.js: PYTHONUTF8=1 injected into spawnSync env — correct approach to force UTF-8 stdout on Windows without affecting other processes.
  • tests/scripts/codex-hooks.test.js: quoted-path test properly gated behind os.platform() !== 'win32'; the skip path correctly leaves passed/failed counters unaffected so CI does not count it as a failure.
  • .mcp.json / .github/workflows/monthly-metrics.yml: MCP server versions pinned; GitHub Actions step pinned to a full commit SHA — good supply-chain hardening.
  • .github/dependabot.yml: new file adds automated weekly dependency updates with minor/patch grouping.

Confidence Score: 5/5

Safe to merge — all changes are targeted cross-platform fixes with no logic regressions and no new risks introduced.

All four CI fixes are correct and narrowly scoped. The search_file() fallback preserves exit-code semantics; POSIX ERE patterns are valid for both rg and grep -E; the Windows path-separator and encoding fixes are idiomatic; the Windows test skip correctly avoids inflating the failure counter. Supply-chain improvements are purely additive. No P0 or P1 findings.

No files require special attention.

Important Files Changed

Filename Overview
scripts/codex/check-codex-global-state.sh Added portable search_file() helper with rg/grep -En fallback; converted all \s shorthands to POSIX [[:space:]] character classes for grep -E compatibility
tests/scripts/codex-hooks.test.js Skips the quoted-path shell-injection test on win32 via platform check; test counter logic is correct — neither passed nor failed is incremented for a skip
tests/scripts/check-unicode-safety.test.js Changed path-separator regex to handle both Unix and Windows path separators in stderr output
tests/scripts/openclaw-persona-forge-gacha.test.js Added PYTHONUTF8=1 to the spawnSync env to force UTF-8 stdout on Windows (which defaults to cp1252)
.mcp.json Pinned all MCP server versions for supply-chain safety; bumped @playwright/mcp from 0.0.68 to 0.0.69
.github/dependabot.yml New file: configures weekly Dependabot updates for npm and github-actions with minor/patch grouping
.github/workflows/monthly-metrics.yml Pinned actions/github-script to a full commit SHA to prevent supply-chain attacks via mutable tag
package.json Bumped markdownlint-cli from ^0.47.0 to ^0.48.0 to resolve audit vulnerabilities

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[CI Test Runner] --> B{Platform?}
    B -->|Windows| C[codex-hooks: skip quoted-path test]
    B -->|Windows| D[gacha test: PYTHONUTF8=1 env var]
    B -->|Windows| E[unicode test: path regex handles backslash]
    B -->|Ubuntu / macOS| F[check-codex-global-state.sh]
    F --> G{rg on PATH?}
    G -->|Yes| H[search_file uses rg -n]
    G -->|No| I[search_file uses grep -En]
    H --> J[Patterns use POSIX ERE character classes]
    I --> J
    J --> K[Exit 0 if match / Exit 1 if not]
Loading

Reviews (6): Last reviewed commit: "fix: replace unicode arrows in lead-inte..." | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/codex/check-codex-global-state.sh (1)

116-116: Escape section names before embedding them in regex patterns.

$section values include . characters, which are regex wildcards. That can allow unintended matches and mask malformed config sections. Consider escaping before building ^\[$section\].

Suggested hardening diff
+escape_ere() {
+  printf '%s' "$1" | sed 's/[][(){}.^$*+?|\\]/\\&/g'
+}
+
   for section in \
     'mcp_servers.github' \
     'mcp_servers.memory' \
     'mcp_servers.sequential-thinking' \
     'mcp_servers.context7'
   do
-    if search_file "^\[$section\]" "$CONFIG_FILE"; then
+    escaped_section="$(escape_ere "$section")"
+    if search_file "^\[$escaped_section\]" "$CONFIG_FILE"; then
       ok "MCP section [$section] exists"
     else
       fail "MCP section [$section] missing"
     fi
   done
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/codex/check-codex-global-state.sh` at line 116, The check embeds
$section directly into the regex "^\[$section\]" which treats dots and other
metacharacters as wildcards; update the code that calls search_file so it first
escapes regex metacharacters in $section (e.g., via a small helper like
escape_regex that backsslashes []\.^$*+?(){}| and so on, or by using a literal/
fixed-string search if search_file supports it), then use the escaped value when
building the pattern (replace "^\[$section\]" with "^\[$escaped_section\]"),
referencing the search_file call, the $section variable, and CONFIG_FILE in your
change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@scripts/codex/check-codex-global-state.sh`:
- Line 116: The check embeds $section directly into the regex "^\[$section\]"
which treats dots and other metacharacters as wildcards; update the code that
calls search_file so it first escapes regex metacharacters in $section (e.g.,
via a small helper like escape_regex that backsslashes []\.^$*+?(){}| and so on,
or by using a literal/ fixed-string search if search_file supports it), then use
the escaped value when building the pattern (replace "^\[$section\]" with
"^\[$escaped_section\]"), referencing the search_file call, the $section
variable, and CONFIG_FILE in your change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cac034e7-33ad-4d75-b806-e500b6bafab5

📥 Commits

Reviewing files that changed from the base of the PR and between e68233c and d728312.

📒 Files selected for processing (4)
  • scripts/codex/check-codex-global-state.sh
  • tests/scripts/check-unicode-safety.test.js
  • tests/scripts/codex-hooks.test.js
  • tests/scripts/openclaw-persona-forge-gacha.test.js

…files

New skill:
- remotion-video-creation: 29 domain-specific Remotion rules covering 3D/Three.js,
  animations, audio, captions, charts, compositions, fonts, GIFs, Lottie,
  measuring, sequencing, tailwind, text animations, timing, transitions,
  trimming, and video embedding. Ported from personal skills.

Restored:
- autonomous-agent-harness/SKILL.md (was in commit but missing from worktree)
- lead-intelligence/ (full directory restored from branch commit)

Updated:
- manifests/install-modules.json: added remotion-video-creation to media-generation
- README.md + AGENTS.md: synced counts to 139 skills

Catalog validates: 30 agents, 60 commands, 139 skills.
@ecc-tools
Copy link
Copy Markdown
Contributor

ecc-tools bot commented Mar 31, 2026

Analyzing 5000 commits...

@ecc-tools
Copy link
Copy Markdown
Contributor

ecc-tools bot commented Mar 31, 2026

Analysis Failed

Not Found - https://docs.github.com/rest/git/refs#get-a-reference

Troubleshooting
Cause Resolution
Large repository Analysis may timeout on repos with extensive history
API rate limits Wait 15 minutes before retrying
Network issues Queue timeout is 15 minutes; retry may succeed
Permissions Verify app has Contents: Read access

Retry: /ecc-tools analyze


Report Issue | ECC Tools

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (3)
skills/lead-intelligence/agents/outreach-drafter.md (1)

16-16: Clarify expected input data format.

Line 16 states the agent receives "enriched prospect profiles and warm path data" but doesn't specify the expected structure. Looking at the upstream agents, there's a potential format mismatch:

  • enrichment-agent (from context snippet 1) outputs Personalization Hooks: [text] as natural language
  • mutual-mapper (from context snippet 2) outputs Via:, Relationship:, Suggested approach:
  • outreach-drafter output (lines 88-91) expects Referenced:, Warm path:, Confidence:

This creates an implicit requirement for the agent to parse natural language from enrichment-agent and transform field names from mutual-mapper. Consider either:

  1. Standardizing field names across all three agents, or
  2. Documenting the input format transformation requirements in this agent's Task section
📋 Suggested clarification

Add an "Input Format" section after line 16:

## Input Format

Expects enriched profile data from `enrichment-agent` and warm path data from `mutual-mapper`:

**From enrichment-agent:**
- Person details (Title, Company, Location, X handle)
- Company intel (Stage, Funding, Headcount, News)
- Recent Activity (tweets/posts with dates)
- Personalization Hooks (natural language text to parse)

**From mutual-mapper:**
- Target name and handle
- Warm path(s) with: Via (mutual name/handle), Relationship (connection type), Suggested approach
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lead-intelligence/agents/outreach-drafter.md` at line 16, Add an
"Input Format" section right after the sentence about receiving "enriched
prospect profiles and warm path data" that explicitly documents the expected
structure and any transformation rules between upstream agents: enumerate fields
produced by enrichment-agent (e.g., Person details, Company intel, Recent
Activity, Personalization Hooks) and by mutual-mapper (e.g., Target name/handle,
Via, Relationship, Suggested approach), and map how those natural-language
fields must be parsed or renamed to the outreach-drafter's expected output
fields (e.g., Referenced:, Warm path:, Confidence:) so the agent knows to parse
"Personalization Hooks" text and convert mutual-mapper
"Via/Relationship/Suggested approach" into the Warm path entries.
skills/lead-intelligence/SKILL.md (1)

144-144: Minor: Hyphenate compound adjective.

When "open source" modifies "contributions" as a compound adjective, it should be hyphenated: "open-source contributions".

📝 Proposed fix
-- GitHub: open source contributions (for developer-centric leads)
+- GitHub: open-source contributions (for developer-centric leads)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lead-intelligence/SKILL.md` at line 144, Replace the un-hyphenated
phrase in the SKILL.md line "GitHub: open source contributions (for
developer-centric leads)" with the hyphenated compound adjective form
"open-source contributions" so it reads "GitHub: open-source contributions (for
developer-centric leads)"; locate the string "GitHub: open source contributions
(for developer-centric leads)" and update it accordingly.
skills/remotion-video-creation/rules/assets/text-animations-typewriter.tsx (1)

20-32: Add fail-fast validation for timing parameters.

At Line 20 and Line 52, invalid values like charFrames <= 0 or blinkFrames <= 0 can cause broken math (frame % 0, divide-by-zero behavior) and hard-to-debug animation output. Add explicit guards with clear errors.

Proposed patch
 const getTypedText = ({
 	frame,
 	fullText,
 	pauseAfter,
 	charFrames,
 	pauseFrames,
 }: {
 	frame: number;
 	fullText: string;
 	pauseAfter: string;
 	charFrames: number;
 	pauseFrames: number;
 }): string => {
+	if (charFrames <= 0) {
+		throw new Error('charFrames must be greater than 0');
+	}
+	if (pauseFrames < 0) {
+		throw new Error('pauseFrames must be greater than or equal to 0');
+	}
+
 	const pauseIndex = fullText.indexOf(pauseAfter);
 	const preLen =
 		pauseIndex >= 0 ? pauseIndex + pauseAfter.length : fullText.length;
@@
 const Cursor: React.FC<{
 	frame: number;
 	blinkFrames: number;
 	symbol?: string;
 }> = ({frame, blinkFrames, symbol = '\u258C'}) => {
+	if (blinkFrames <= 0) {
+		throw new Error('blinkFrames must be greater than 0');
+	}
+
 	const opacity = interpolate(
 		frame % blinkFrames,
 		[0, blinkFrames / 2, blinkFrames],
As per coding guidelines "Fail fast with clear error messages when validation fails" and "Always handle errors explicitly at every level and never silently swallow errors".

Also applies to: 52-60

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/remotion-video-creation/rules/assets/text-animations-typewriter.tsx`
around lines 20 - 32, Add fail-fast validation in getTypedText to guard against
invalid timing parameters: check that charFrames and pauseFrames are positive
integers and that pauseAfter is a valid index/range; if any check fails, throw a
clear Error (e.g., "getTypedText: charFrames must be > 0, got X"). Also add the
same validation for the cursor-blink routine that uses blinkFrames (the function
handling blinkFrames around lines 52-60): ensure blinkFrames > 0 and throw a
descriptive Error if not. Keep messages specific to the parameter and function
name so failures point to the exact invalid value and location.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@skills/remotion-video-creation/rules/charts.md`:
- Line 14: Update the documentation text to correct the two typos: change the
phrase "third party" in the sentence "Disable all animations by third party
libraries." to the compound adjective "third-party", and correct the misspelling
"implmentation" to "implementation" wherever it appears (notably the instance on
line 20) in the charts.md content.
- Line 20: Update the broken link in charts.md that points to
"assets/charts/bar-chart.tsx": change the path to the correct asset file name
"assets/charts-bar-chart.tsx" (remove the non-existent "charts/" subdirectory
and use the hyphenated filename) so the Bar Chart Example link resolves to the
existing asset.

In `@skills/remotion-video-creation/rules/display-captions.md`:
- Around line 8-126: Reorganize the document to match the required "When to
Use", "How It Works", and "Examples" sections: add a brief "When to Use" that
describes scenarios for caption display, move the "Prerequisites" and the
createTikTokStyleCaptions usage (including useMemo and SWITCH_CAPTIONS_EVERY_MS)
plus the Sequence rendering logic (pages, Sequence,
startFrame/endFrame/durationInFrames) into a combined "How It Works" section,
and place the word-highlighting example (CaptionPage, useCurrentFrame,
useVideoConfig, TikTokPage, page.tokens and token timing logic) into an
"Examples" section; preserve all technical details and referenced symbols
(createTikTokStyleCaptions, pages, SWITCH_CAPTIONS_EVERY_MS, Sequence,
CaptionPage, TikTokPage) and ensure headings are Markdown-formatted as required.
- Around line 109-121: The current React key uses token.fromMs which can
collide; update the map callback in page.tokens.map to accept the index
(map((token, idx) => ...)) and set a stable unique key combining fromMs with
either the index or token text (e.g., `${token.fromMs}-${idx}` or
`${token.fromMs}-${token.text}`) on the <span> so keys are deterministic and
unique (change reference to token.fromMs in the key prop).

In `@skills/remotion-video-creation/rules/extract-frames.md`:
- Around line 196-205: The timeout Promise can still reject after
extractFrames() wins the race; change the Promise.race usage so the timeout
timer is cleared when extractFrames resolves: capture the timeoutId created
inside timeoutPromise (or move timeoutId to an outer scope), then when invoking
Promise.race([extractFrames(), timeoutPromise]) attach a .then/.finally handler
on the successful extractFrames call (or wrap extractFrames in a small wrapper)
to call clearTimeout(timeoutId) and remove any listeners on controller.signal;
reference timeoutPromise, timeoutId, controller.signal, extractFrames(), and the
Promise.race call to locate where to add the clearTimeout on success.
- Around line 8-191: The document is missing the required skill-document
sections; add explicit "When to Use", "How It Works", and "Examples" headings to
the markdown around the existing content so it matches the skills/*.md
format—insert a "When to Use" section summarizing scenarios for extractFrames(),
a "How It Works" section describing the flow (Input,
computeDuration/getFormat/getPrimaryVideoTrack, timestamps resolution,
VideoSampleSink.samplesAtTimestamps, AbortSignal handling) and an "Examples"
section that includes the provided usage, filmstrip, and cancellation snippets
(referencing ExtractFramesProps, extractFrames, and VideoSampleSink) so the doc
validates against the required structure.

In `@skills/remotion-video-creation/rules/fonts.md`:
- Line 36: Fix the spelling in the Markdown sentence "Preferrably, specify only
needed weights and subsets to reduce file size:" by replacing "Preferrably" with
"Preferably" wherever that exact phrase appears (e.g., in the fonts.md content
string) so the user-facing docs read "Preferably, specify only needed weights
and subsets to reduce file size:".
- Around line 8-152: Add the three mandatory skill doc sections "When to Use",
"How It Works", and "Examples" to this markdown: create a "When to Use" section
under the top-level "Using fonts in Remotion" that explains scenarios for
choosing Google vs local fonts, a "How It Works" section that briefly describes
the APIs and flow (mention `@remotion/google-fonts` loadFont and waitUntilDone,
and `@remotion/fonts` loadFont with staticFile), and an "Examples" section that
includes short, focused examples already in the file (the Google Fonts snippets
using loadFont from `@remotion/google-fonts` and the local font snippets using
`@remotion/fonts` + staticFile) so the doc conforms to the skills/**/*.md required
structure.

In `@skills/remotion-video-creation/rules/tailwind.md`:
- Around line 7-11: The skill doc is missing the required sections; add clear
Markdown headings "When to Use", "How It Works", and "Examples" to
skills/remotion-video-creation/rules/tailwind.md; under "When to Use" state when
Tailwind in Remotion is appropriate, under "How It Works" describe that Tailwind
must be installed/enabled (fetch https://www.remotion.dev/docs/tailwind using
WebFetch) and explain the rule "Don't use transition-* or animate-*; always
animate using useCurrentFrame()", and under "Examples" show one or two concise
examples demonstrating Tailwind utility classes for styling combined with an
animation implemented via the useCurrentFrame() hook (reference useCurrentFrame
and Tailwind classes in the text).

---

Nitpick comments:
In `@skills/lead-intelligence/agents/outreach-drafter.md`:
- Line 16: Add an "Input Format" section right after the sentence about
receiving "enriched prospect profiles and warm path data" that explicitly
documents the expected structure and any transformation rules between upstream
agents: enumerate fields produced by enrichment-agent (e.g., Person details,
Company intel, Recent Activity, Personalization Hooks) and by mutual-mapper
(e.g., Target name/handle, Via, Relationship, Suggested approach), and map how
those natural-language fields must be parsed or renamed to the
outreach-drafter's expected output fields (e.g., Referenced:, Warm path:,
Confidence:) so the agent knows to parse "Personalization Hooks" text and
convert mutual-mapper "Via/Relationship/Suggested approach" into the Warm path
entries.

In `@skills/lead-intelligence/SKILL.md`:
- Line 144: Replace the un-hyphenated phrase in the SKILL.md line "GitHub: open
source contributions (for developer-centric leads)" with the hyphenated compound
adjective form "open-source contributions" so it reads "GitHub: open-source
contributions (for developer-centric leads)"; locate the string "GitHub: open
source contributions (for developer-centric leads)" and update it accordingly.

In `@skills/remotion-video-creation/rules/assets/text-animations-typewriter.tsx`:
- Around line 20-32: Add fail-fast validation in getTypedText to guard against
invalid timing parameters: check that charFrames and pauseFrames are positive
integers and that pauseAfter is a valid index/range; if any check fails, throw a
clear Error (e.g., "getTypedText: charFrames must be > 0, got X"). Also add the
same validation for the cursor-blink routine that uses blinkFrames (the function
handling blinkFrames around lines 52-60): ensure blinkFrames > 0 and throw a
descriptive Error if not. Keep messages specific to the parameter and function
name so failures point to the exact invalid value and location.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 482f5ee2-e4bb-4411-ba2d-94842cd52bdc

📥 Commits

Reviewing files that changed from the base of the PR and between d728312 and df76bdf.

📒 Files selected for processing (41)
  • AGENTS.md
  • README.md
  • manifests/install-modules.json
  • skills/autonomous-agent-harness/SKILL.md
  • skills/lead-intelligence/SKILL.md
  • skills/lead-intelligence/agents/enrichment-agent.md
  • skills/lead-intelligence/agents/mutual-mapper.md
  • skills/lead-intelligence/agents/outreach-drafter.md
  • skills/lead-intelligence/agents/signal-scorer.md
  • skills/remotion-video-creation/SKILL.md
  • skills/remotion-video-creation/rules/3d.md
  • skills/remotion-video-creation/rules/animations.md
  • skills/remotion-video-creation/rules/assets.md
  • skills/remotion-video-creation/rules/assets/charts-bar-chart.tsx
  • skills/remotion-video-creation/rules/assets/text-animations-typewriter.tsx
  • skills/remotion-video-creation/rules/assets/text-animations-word-highlight.tsx
  • skills/remotion-video-creation/rules/audio.md
  • skills/remotion-video-creation/rules/calculate-metadata.md
  • skills/remotion-video-creation/rules/can-decode.md
  • skills/remotion-video-creation/rules/charts.md
  • skills/remotion-video-creation/rules/compositions.md
  • skills/remotion-video-creation/rules/display-captions.md
  • skills/remotion-video-creation/rules/extract-frames.md
  • skills/remotion-video-creation/rules/fonts.md
  • skills/remotion-video-creation/rules/get-audio-duration.md
  • skills/remotion-video-creation/rules/get-video-dimensions.md
  • skills/remotion-video-creation/rules/get-video-duration.md
  • skills/remotion-video-creation/rules/gifs.md
  • skills/remotion-video-creation/rules/images.md
  • skills/remotion-video-creation/rules/import-srt-captions.md
  • skills/remotion-video-creation/rules/lottie.md
  • skills/remotion-video-creation/rules/measuring-dom-nodes.md
  • skills/remotion-video-creation/rules/measuring-text.md
  • skills/remotion-video-creation/rules/sequencing.md
  • skills/remotion-video-creation/rules/tailwind.md
  • skills/remotion-video-creation/rules/text-animations.md
  • skills/remotion-video-creation/rules/timing.md
  • skills/remotion-video-creation/rules/transcribe-captions.md
  • skills/remotion-video-creation/rules/transitions.md
  • skills/remotion-video-creation/rules/trimming.md
  • skills/remotion-video-creation/rules/videos.md
✅ Files skipped from review due to trivial changes (31)
  • AGENTS.md
  • manifests/install-modules.json
  • skills/remotion-video-creation/rules/transitions.md
  • skills/remotion-video-creation/rules/transcribe-captions.md
  • skills/remotion-video-creation/SKILL.md
  • skills/remotion-video-creation/rules/text-animations.md
  • skills/remotion-video-creation/rules/get-audio-duration.md
  • skills/remotion-video-creation/rules/trimming.md
  • skills/remotion-video-creation/rules/measuring-text.md
  • README.md
  • skills/remotion-video-creation/rules/import-srt-captions.md
  • skills/remotion-video-creation/rules/assets.md
  • skills/remotion-video-creation/rules/sequencing.md
  • skills/remotion-video-creation/rules/measuring-dom-nodes.md
  • skills/remotion-video-creation/rules/get-video-dimensions.md
  • skills/remotion-video-creation/rules/get-video-duration.md
  • skills/remotion-video-creation/rules/lottie.md
  • skills/lead-intelligence/agents/signal-scorer.md
  • skills/lead-intelligence/agents/mutual-mapper.md
  • skills/lead-intelligence/agents/enrichment-agent.md
  • skills/remotion-video-creation/rules/can-decode.md
  • skills/autonomous-agent-harness/SKILL.md
  • skills/remotion-video-creation/rules/timing.md
  • skills/remotion-video-creation/rules/3d.md
  • skills/remotion-video-creation/rules/audio.md
  • skills/remotion-video-creation/rules/animations.md
  • skills/remotion-video-creation/rules/images.md
  • skills/remotion-video-creation/rules/gifs.md
  • skills/remotion-video-creation/rules/videos.md
  • skills/remotion-video-creation/rules/compositions.md
  • skills/remotion-video-creation/rules/calculate-metadata.md


## No animations not powered by `useCurrentFrame()`

Disable all animations by third party libraries.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Minor text issues flagged by static analysis.

  • Line 14: "third party" → "third-party" (compound adjective)
  • Line 20: "implmentation" → "implementation" (typo)
📝 Proposed fix
-Disable all animations by third party libraries.  
+Disable all animations by third-party libraries.  
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Disable all animations by third party libraries.
Disable all animations by third-party libraries.
🧰 Tools
🪛 LanguageTool

[grammar] ~14-~14: Use a hyphen to join words.
Context: ...rame()` Disable all animations by third party libraries. They will cause flick...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/remotion-video-creation/rules/charts.md` at line 14, Update the
documentation text to correct the two typos: change the phrase "third party" in
the sentence "Disable all animations by third party libraries." to the compound
adjective "third-party", and correct the misspelling "implmentation" to
"implementation" wherever it appears (notably the instance on line 20) in the
charts.md content.


## Bar Chart Animations

See [Bar Chart Example](assets/charts/bar-chart.tsx) for a basic example implmentation.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Broken link to bar chart example.

The link references assets/charts/bar-chart.tsx, but the actual asset file is assets/charts-bar-chart.tsx. This path has a non-existent charts/ subdirectory and incorrect filename.

📝 Proposed fix
-See [Bar Chart Example](assets/charts/bar-chart.tsx) for a basic example implmentation.
+See [Bar Chart Example](assets/charts-bar-chart.tsx) for a basic example implementation.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
See [Bar Chart Example](assets/charts/bar-chart.tsx) for a basic example implmentation.
See [Bar Chart Example](assets/charts-bar-chart.tsx) for a basic example implementation.
🧰 Tools
🪛 LanguageTool

[grammar] ~20-~20: Ensure spelling is correct
Context: ...arts/bar-chart.tsx) for a basic example implmentation. ### Staggered Bars You can animate the heig...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/remotion-video-creation/rules/charts.md` at line 20, Update the broken
link in charts.md that points to "assets/charts/bar-chart.tsx": change the path
to the correct asset file name "assets/charts-bar-chart.tsx" (remove the
non-existent "charts/" subdirectory and use the hyphenated filename) so the Bar
Chart Example link resolves to the existing asset.

Comment on lines +8 to +126
# Displaying captions in Remotion

This guide explains how to display captions in Remotion, assuming you already have captions in the `Caption` format.

## Prerequisites

First, the @remotion/captions package needs to be installed.
If it is not installed, use the following command:

```bash
npx remotion add @remotion/captions # If project uses npm
bunx remotion add @remotion/captions # If project uses bun
yarn remotion add @remotion/captions # If project uses yarn
pnpm exec remotion add @remotion/captions # If project uses pnpm
```

## Creating pages

Use `createTikTokStyleCaptions()` to group captions into pages. The `combineTokensWithinMilliseconds` option controls how many words appear at once:

```tsx
import {useMemo} from 'react';
import {createTikTokStyleCaptions} from '@remotion/captions';
import type {Caption} from '@remotion/captions';

// How often captions should switch (in milliseconds)
// Higher values = more words per page
// Lower values = fewer words (more word-by-word)
const SWITCH_CAPTIONS_EVERY_MS = 1200;

const {pages} = useMemo(() => {
return createTikTokStyleCaptions({
captions,
combineTokensWithinMilliseconds: SWITCH_CAPTIONS_EVERY_MS,
});
}, [captions]);
```

## Rendering with Sequences

Map over the pages and render each one in a `<Sequence>`. Calculate the start frame and duration from the page timing:

```tsx
import {Sequence, useVideoConfig, AbsoluteFill} from 'remotion';
import type {TikTokPage} from '@remotion/captions';

const CaptionedContent: React.FC = () => {
const {fps} = useVideoConfig();

return (
<AbsoluteFill>
{pages.map((page, index) => {
const nextPage = pages[index + 1] ?? null;
const startFrame = (page.startMs / 1000) * fps;
const endFrame = Math.min(
nextPage ? (nextPage.startMs / 1000) * fps : Infinity,
startFrame + (SWITCH_CAPTIONS_EVERY_MS / 1000) * fps,
);
const durationInFrames = endFrame - startFrame;

if (durationInFrames <= 0) {
return null;
}

return (
<Sequence
key={index}
from={startFrame}
durationInFrames={durationInFrames}
>
<CaptionPage page={page} />
</Sequence>
);
})}
</AbsoluteFill>
);
};
```

## Word highlighting

A caption page contains `tokens` which you can use to highlight the currently spoken word:

```tsx
import {AbsoluteFill, useCurrentFrame, useVideoConfig} from 'remotion';
import type {TikTokPage} from '@remotion/captions';

const HIGHLIGHT_COLOR = '#39E508';

const CaptionPage: React.FC<{page: TikTokPage}> = ({page}) => {
const frame = useCurrentFrame();
const {fps} = useVideoConfig();

// Current time relative to the start of the sequence
const currentTimeMs = (frame / fps) * 1000;
// Convert to absolute time by adding the page start
const absoluteTimeMs = page.startMs + currentTimeMs;

return (
<AbsoluteFill style={{justifyContent: 'center', alignItems: 'center'}}>
<div style={{fontSize: 80, fontWeight: 'bold', whiteSpace: 'pre'}}>
{page.tokens.map((token) => {
const isActive =
token.fromMs <= absoluteTimeMs && token.toMs > absoluteTimeMs;

return (
<span
key={token.fromMs}
style={{color: isActive ? HIGHLIGHT_COLOR : 'white'}}
>
{token.text}
</span>
);
})}
</div>
</AbsoluteFill>
);
};
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Section structure violates coding guidelines.

The file uses sections "Prerequisites", "Creating pages", "Rendering with Sequences", and "Word highlighting", but the coding guidelines require: "When to Use, How It Works, and Examples".

Please reorganize the content to follow the required structure. As per coding guidelines: Skill format must be Markdown with clear sections for When to Use, How It Works, and Examples.

💡 Suggested section reorganization

Consider restructuring as:

  • When to Use: Explain scenarios where caption display is needed (currently missing)
  • How It Works: Cover the Prerequisites, TikTok-style page creation, and Sequence rendering (merge lines 12-85)
  • Examples: Show the complete word highlighting example (lines 87-126)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/remotion-video-creation/rules/display-captions.md` around lines 8 -
126, Reorganize the document to match the required "When to Use", "How It
Works", and "Examples" sections: add a brief "When to Use" that describes
scenarios for caption display, move the "Prerequisites" and the
createTikTokStyleCaptions usage (including useMemo and SWITCH_CAPTIONS_EVERY_MS)
plus the Sequence rendering logic (pages, Sequence,
startFrame/endFrame/durationInFrames) into a combined "How It Works" section,
and place the word-highlighting example (CaptionPage, useCurrentFrame,
useVideoConfig, TikTokPage, page.tokens and token timing logic) into an
"Examples" section; preserve all technical details and referenced symbols
(createTikTokStyleCaptions, pages, SWITCH_CAPTIONS_EVERY_MS, Sequence,
CaptionPage, TikTokPage) and ensure headings are Markdown-formatted as required.

Comment on lines +109 to +121
{page.tokens.map((token) => {
const isActive =
token.fromMs <= absoluteTimeMs && token.toMs > absoluteTimeMs;

return (
<span
key={token.fromMs}
style={{color: isActive ? HIGHLIGHT_COLOR : 'white'}}
>
{token.text}
</span>
);
})}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Potential React key uniqueness issue.

Line 115 uses token.fromMs as the React key, but multiple tokens could theoretically start at the same millisecond, causing key collisions. Consider using the array index or a combination of fromMs and the token text for uniqueness.

🔑 Proposed fix for unique keys
         {page.tokens.map((token) => {
           const isActive =
             token.fromMs <= absoluteTimeMs && token.toMs > absoluteTimeMs;

           return (
             <span
-              key={token.fromMs}
+              key={`${token.fromMs}-${token.text}`}
               style={{color: isActive ? HIGHLIGHT_COLOR : 'white'}}
             >
               {token.text}
             </span>
           );
         })}

Alternatively, if the token order is stable:

-        {page.tokens.map((token) => {
+        {page.tokens.map((token, tokenIndex) => {
           const isActive =
             token.fromMs <= absoluteTimeMs && token.toMs > absoluteTimeMs;

           return (
             <span
-              key={token.fromMs}
+              key={tokenIndex}
               style={{color: isActive ? HIGHLIGHT_COLOR : 'white'}}
             >
               {token.text}
             </span>
           );
         })}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{page.tokens.map((token) => {
const isActive =
token.fromMs <= absoluteTimeMs && token.toMs > absoluteTimeMs;
return (
<span
key={token.fromMs}
style={{color: isActive ? HIGHLIGHT_COLOR : 'white'}}
>
{token.text}
</span>
);
})}
{page.tokens.map((token) => {
const isActive =
token.fromMs <= absoluteTimeMs && token.toMs > absoluteTimeMs;
return (
<span
key={`${token.fromMs}-${token.text}`}
style={{color: isActive ? HIGHLIGHT_COLOR : 'white'}}
>
{token.text}
</span>
);
})}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/remotion-video-creation/rules/display-captions.md` around lines 109 -
121, The current React key uses token.fromMs which can collide; update the map
callback in page.tokens.map to accept the index (map((token, idx) => ...)) and
set a stable unique key combining fromMs with either the index or token text
(e.g., `${token.fromMs}-${idx}` or `${token.fromMs}-${token.text}`) on the
<span> so keys are deterministic and unique (change reference to token.fromMs in
the key prop).

Comment on lines +8 to +191
# Extracting frames from videos

Use Mediabunny to extract frames from videos at specific timestamps. This is useful for generating thumbnails, filmstrips, or processing individual frames.

## The `extractFrames()` function

This function can be copy-pasted into any project.

```tsx
import {
ALL_FORMATS,
Input,
UrlSource,
VideoSample,
VideoSampleSink,
} from "mediabunny";

type Options = {
track: { width: number; height: number };
container: string;
durationInSeconds: number | null;
};

export type ExtractFramesTimestampsInSecondsFn = (
options: Options
) => Promise<number[]> | number[];

export type ExtractFramesProps = {
src: string;
timestampsInSeconds: number[] | ExtractFramesTimestampsInSecondsFn;
onVideoSample: (sample: VideoSample) => void;
signal?: AbortSignal;
};

export async function extractFrames({
src,
timestampsInSeconds,
onVideoSample,
signal,
}: ExtractFramesProps): Promise<void> {
using input = new Input({
formats: ALL_FORMATS,
source: new UrlSource(src),
});

const [durationInSeconds, format, videoTrack] = await Promise.all([
input.computeDuration(),
input.getFormat(),
input.getPrimaryVideoTrack(),
]);

if (!videoTrack) {
throw new Error("No video track found in the input");
}

if (signal?.aborted) {
throw new Error("Aborted");
}

const timestamps =
typeof timestampsInSeconds === "function"
? await timestampsInSeconds({
track: {
width: videoTrack.displayWidth,
height: videoTrack.displayHeight,
},
container: format.name,
durationInSeconds,
})
: timestampsInSeconds;

if (timestamps.length === 0) {
return;
}

if (signal?.aborted) {
throw new Error("Aborted");
}

const sink = new VideoSampleSink(videoTrack);

for await (using videoSample of sink.samplesAtTimestamps(timestamps)) {
if (signal?.aborted) {
break;
}

if (!videoSample) {
continue;
}

onVideoSample(videoSample);
}
}
```

## Basic usage

Extract frames at specific timestamps:

```tsx
await extractFrames({
src: "https://remotion.media/video.mp4",
timestampsInSeconds: [0, 1, 2, 3, 4],
onVideoSample: (sample) => {
const canvas = document.createElement("canvas");
canvas.width = sample.displayWidth;
canvas.height = sample.displayHeight;
const ctx = canvas.getContext("2d");
sample.draw(ctx!, 0, 0);
},
});
```

## Creating a filmstrip

Use a callback function to dynamically calculate timestamps based on video metadata:

```tsx
const canvasWidth = 500;
const canvasHeight = 80;
const fromSeconds = 0;
const toSeconds = 10;

await extractFrames({
src: "https://remotion.media/video.mp4",
timestampsInSeconds: async ({ track, durationInSeconds }) => {
const aspectRatio = track.width / track.height;
const amountOfFramesFit = Math.ceil(
canvasWidth / (canvasHeight * aspectRatio)
);
const segmentDuration = toSeconds - fromSeconds;
const timestamps: number[] = [];

for (let i = 0; i < amountOfFramesFit; i++) {
timestamps.push(
fromSeconds + (segmentDuration / amountOfFramesFit) * (i + 0.5)
);
}

return timestamps;
},
onVideoSample: (sample) => {
console.log(`Frame at ${sample.timestamp}s`);

const canvas = document.createElement("canvas");
canvas.width = sample.displayWidth;
canvas.height = sample.displayHeight;
const ctx = canvas.getContext("2d");
sample.draw(ctx!, 0, 0);
},
});
```

## Cancellation with AbortSignal

Cancel frame extraction after a timeout:

```tsx
const controller = new AbortController();

setTimeout(() => controller.abort(), 5000);

try {
await extractFrames({
src: "https://remotion.media/video.mp4",
timestampsInSeconds: [0, 1, 2, 3, 4],
onVideoSample: (sample) => {
using frame = sample;
const canvas = document.createElement("canvas");
canvas.width = frame.displayWidth;
canvas.height = frame.displayHeight;
const ctx = canvas.getContext("2d");
frame.draw(ctx!, 0, 0);
},
signal: controller.signal,
});

console.log("Frame extraction complete!");
} catch (error) {
console.error("Frame extraction was aborted or failed:", error);
}
```

## Timeout with Promise.race
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing required skill-document section structure.

This doc is well-written, but it does not include the required explicit sections When to Use, How It Works, and Examples.

📌 Suggested structure update
 # Extracting frames from videos
 
 Use Mediabunny to extract frames from videos at specific timestamps. This is useful for generating thumbnails, filmstrips, or processing individual frames.
+
+## When to Use
+
+- Generate thumbnails at fixed timestamps
+- Build filmstrips/previews
+- Run per-frame processing pipelines
+
+## How It Works
+
+1. Open input with Mediabunny
+2. Resolve duration/format/primary video track
+3. Resolve timestamps (array or callback)
+4. Iterate samples via `VideoSampleSink`
+5. Invoke `onVideoSample` for each frame (with abort support)
 
 ## The `extractFrames()` function
@@
-## Basic usage
+## Examples
+
+### Basic usage
@@
-## Creating a filmstrip
+### Creating a filmstrip
@@
-## Cancellation with AbortSignal
+### Cancellation with AbortSignal
@@
-## Timeout with Promise.race
+### Timeout with Promise.race

As per coding guidelines, "skills/**/*.md: Skill format must be Markdown with clear sections for When to Use, How It Works, and Examples".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/remotion-video-creation/rules/extract-frames.md` around lines 8 - 191,
The document is missing the required skill-document sections; add explicit "When
to Use", "How It Works", and "Examples" headings to the markdown around the
existing content so it matches the skills/*.md format—insert a "When to Use"
section summarizing scenarios for extractFrames(), a "How It Works" section
describing the flow (Input, computeDuration/getFormat/getPrimaryVideoTrack,
timestamps resolution, VideoSampleSink.samplesAtTimestamps, AbortSignal
handling) and an "Examples" section that includes the provided usage, filmstrip,
and cancellation snippets (referencing ExtractFramesProps, extractFrames, and
VideoSampleSink) so the doc validates against the required structure.

Comment on lines +196 to +205
const timeoutPromise = new Promise<never>((_, reject) => {
const timeoutId = setTimeout(() => {
controller.abort();
reject(new Error("Frame extraction timed out after 10 seconds"));
}, 10000);

controller.signal.addEventListener("abort", () => clearTimeout(timeoutId), {
once: true,
});
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Clear timeout on success to avoid delayed rejection from the raced promise.

In the timeout example, timeoutPromise can still reject later after extractFrames() resolves, because the timer is only cleared on abort.

✅ Safer Promise.race example
 const controller = new AbortController();
+let timeoutId: ReturnType<typeof setTimeout> | undefined;
 
 const timeoutPromise = new Promise<never>((_, reject) => {
-  const timeoutId = setTimeout(() => {
+  timeoutId = setTimeout(() => {
     controller.abort();
     reject(new Error("Frame extraction timed out after 10 seconds"));
   }, 10000);
 
   controller.signal.addEventListener("abort", () => clearTimeout(timeoutId), {
     once: true,
   });
 });
 
 try {
   await Promise.race([
@@
     timeoutPromise,
   ]);
 
   console.log("Frame extraction complete!");
 } catch (error) {
   console.error("Frame extraction was aborted or failed:", error);
+} finally {
+  if (timeoutId) clearTimeout(timeoutId);
 }

Also applies to: 207-223

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/remotion-video-creation/rules/extract-frames.md` around lines 196 -
205, The timeout Promise can still reject after extractFrames() wins the race;
change the Promise.race usage so the timeout timer is cleared when extractFrames
resolves: capture the timeoutId created inside timeoutPromise (or move timeoutId
to an outer scope), then when invoking Promise.race([extractFrames(),
timeoutPromise]) attach a .then/.finally handler on the successful extractFrames
call (or wrap extractFrames in a small wrapper) to call clearTimeout(timeoutId)
and remove any listeners on controller.signal; reference timeoutPromise,
timeoutId, controller.signal, extractFrames(), and the Promise.race call to
locate where to add the clearTimeout on success.

Comment on lines +8 to +152
# Using fonts in Remotion

## Google Fonts with @remotion/google-fonts

The recommended way to use Google Fonts. It's type-safe and automatically blocks rendering until the font is ready.

### Prerequisites

First, the @remotion/google-fonts package needs to be installed.
If it is not installed, use the following command:

```bash
npx remotion add @remotion/google-fonts # If project uses npm
bunx remotion add @remotion/google-fonts # If project uses bun
yarn remotion add @remotion/google-fonts # If project uses yarn
pnpm exec remotion add @remotion/google-fonts # If project uses pnpm
```

```tsx
import { loadFont } from "@remotion/google-fonts/Lobster";

const { fontFamily } = loadFont();

export const MyComposition = () => {
return <div style={{ fontFamily }}>Hello World</div>;
};
```

Preferrably, specify only needed weights and subsets to reduce file size:

```tsx
import { loadFont } from "@remotion/google-fonts/Roboto";

const { fontFamily } = loadFont("normal", {
weights: ["400", "700"],
subsets: ["latin"],
});
```

### Waiting for font to load

Use `waitUntilDone()` if you need to know when the font is ready:

```tsx
import { loadFont } from "@remotion/google-fonts/Lobster";

const { fontFamily, waitUntilDone } = loadFont();

await waitUntilDone();
```

## Local fonts with @remotion/fonts

For local font files, use the `@remotion/fonts` package.

### Prerequisites

First, install @remotion/fonts:

```bash
npx remotion add @remotion/fonts # If project uses npm
bunx remotion add @remotion/fonts # If project uses bun
yarn remotion add @remotion/fonts # If project uses yarn
pnpm exec remotion add @remotion/fonts # If project uses pnpm
```

### Loading a local font

Place your font file in the `public/` folder and use `loadFont()`:

```tsx
import { loadFont } from "@remotion/fonts";
import { staticFile } from "remotion";

await loadFont({
family: "MyFont",
url: staticFile("MyFont-Regular.woff2"),
});

export const MyComposition = () => {
return <div style={{ fontFamily: "MyFont" }}>Hello World</div>;
};
```

### Loading multiple weights

Load each weight separately with the same family name:

```tsx
import { loadFont } from "@remotion/fonts";
import { staticFile } from "remotion";

await Promise.all([
loadFont({
family: "Inter",
url: staticFile("Inter-Regular.woff2"),
weight: "400",
}),
loadFont({
family: "Inter",
url: staticFile("Inter-Bold.woff2"),
weight: "700",
}),
]);
```

### Available options

```tsx
loadFont({
family: "MyFont", // Required: name to use in CSS
url: staticFile("font.woff2"), // Required: font file URL
format: "woff2", // Optional: auto-detected from extension
weight: "400", // Optional: font weight
style: "normal", // Optional: normal or italic
display: "block", // Optional: font-display behavior
});
```

## Using in components

Call `loadFont()` at the top level of your component or in a separate file that's imported early:

```tsx
import { loadFont } from "@remotion/google-fonts/Montserrat";

const { fontFamily } = loadFont("normal", {
weights: ["400", "700"],
subsets: ["latin"],
});

export const Title: React.FC<{ text: string }> = ({ text }) => {
return (
<h1
style={{
fontFamily,
fontSize: 80,
fontWeight: "bold",
}}
>
{text}
</h1>
);
};
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add required skill sections (When to Use, How It Works, Examples).

This file is well-written, but it does not use the mandatory section structure required for skill docs. Please add clearly named sections for all three required headings.

As per coding guidelines, skills/**/*.md: "Skill format must be Markdown with clear sections for When to Use, How It Works, and Examples".

🧰 Tools
🪛 LanguageTool

[grammar] ~35-~35: Ensure spelling is correct
Context: ...ontFamily }}>Hello World; }; ``` Preferrably, specify only needed weights and subset...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/remotion-video-creation/rules/fonts.md` around lines 8 - 152, Add the
three mandatory skill doc sections "When to Use", "How It Works", and "Examples"
to this markdown: create a "When to Use" section under the top-level "Using
fonts in Remotion" that explains scenarios for choosing Google vs local fonts, a
"How It Works" section that briefly describes the APIs and flow (mention
`@remotion/google-fonts` loadFont and waitUntilDone, and `@remotion/fonts` loadFont
with staticFile), and an "Examples" section that includes short, focused
examples already in the file (the Google Fonts snippets using loadFont from
`@remotion/google-fonts` and the local font snippets using `@remotion/fonts` +
staticFile) so the doc conforms to the skills/**/*.md required structure.

};
```

Preferrably, specify only needed weights and subsets to reduce file size:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix typo: “Preferrably” → “Preferably”.

Small spelling issue in user-facing docs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/remotion-video-creation/rules/fonts.md` at line 36, Fix the spelling
in the Markdown sentence "Preferrably, specify only needed weights and subsets
to reduce file size:" by replacing "Preferrably" with "Preferably" wherever that
exact phrase appears (e.g., in the fonts.md content string) so the user-facing
docs read "Preferably, specify only needed weights and subsets to reduce file
size:".

Comment on lines +7 to +11
You can and should use TailwindCSS in Remotion, if TailwindCSS is installed in the project.

Don't use `transition-*` or `animate-*` classes - always animate using the `useCurrentFrame()` hook.

Tailwind must be installed and enabled first in a Remotion project - fetch https://www.remotion.dev/docs/tailwind using WebFetch for instructions. No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add the required skill sections (When to Use, How It Works, Examples).

This new skill doc is missing the required section structure for skills/**/*.md.

Proposed structure update
-You can and should use TailwindCSS in Remotion, if TailwindCSS is installed in the project.
-
-Don't use `transition-*` or `animate-*` classes - always animate using the `useCurrentFrame()` hook.  
-
-Tailwind must be installed and enabled first in a Remotion project - fetch  https://www.remotion.dev/docs/tailwind using WebFetch for instructions.
+## When to Use
+
+Use TailwindCSS in Remotion projects only when Tailwind is already installed and enabled.
+
+## How It Works
+
+- Tailwind utility classes are allowed for styling.
+- Do **not** use `transition-*` or `animate-*` classes.
+- Drive animation values using Remotion’s `useCurrentFrame()` hook.
+
+## Examples
+
+- ✅ Static styling with Tailwind utility classes.
+- ✅ Frame-driven animation logic via `useCurrentFrame()`.
+- ❌ Tailwind `transition-*` or `animate-*` classes for motion.
+
+For setup instructions, fetch https://www.remotion.dev/docs/tailwind using WebFetch.

As per coding guidelines, skills/**/*.md: Skill format must be Markdown with clear sections for When to Use, How It Works, and Examples.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
You can and should use TailwindCSS in Remotion, if TailwindCSS is installed in the project.
Don't use `transition-*` or `animate-*` classes - always animate using the `useCurrentFrame()` hook.
Tailwind must be installed and enabled first in a Remotion project - fetch https://www.remotion.dev/docs/tailwind using WebFetch for instructions.
## When to Use
Use TailwindCSS in Remotion projects only when Tailwind is already installed and enabled.
## How It Works
- Tailwind utility classes are allowed for styling.
- Do **not** use `transition-*` or `animate-*` classes.
- Drive animation values using Remotion's `useCurrentFrame()` hook.
## Examples
- ✅ Static styling with Tailwind utility classes.
- ✅ Frame-driven animation logic via `useCurrentFrame()`.
- ❌ Tailwind `transition-*` or `animate-*` classes for motion.
For setup instructions, fetch https://www.remotion.dev/docs/tailwind using WebFetch.
🧰 Tools
🪛 LanguageTool

[grammar] ~7-~7: Ensure spelling is correct
Context: ... should use TailwindCSS in Remotion, if TailwindCSS is installed in the project. Don't use...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/remotion-video-creation/rules/tailwind.md` around lines 7 - 11, The
skill doc is missing the required sections; add clear Markdown headings "When to
Use", "How It Works", and "Examples" to
skills/remotion-video-creation/rules/tailwind.md; under "When to Use" state when
Tailwind in Remotion is appropriate, under "How It Works" describe that Tailwind
must be installed/enabled (fetch https://www.remotion.dev/docs/tailwind using
WebFetch) and explain the rule "Don't use transition-* or animate-*; always
animate using useCurrentFrame()", and under "Examples" show one or two concise
examples demonstrating Tailwind utility classes for styling combined with an
animation implemented via the useCurrentFrame() hook (reference useCurrentFrame
and Tailwind classes in the text).

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 issues found across 41 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="skills/remotion-video-creation/rules/animations.md">

<violation number="1" location="skills/remotion-video-creation/rules/animations.md:12">
P3: The example code uses `useVideoConfig` and `interpolate` without importing them, so the snippet won’t compile as written. Include the missing imports so readers can copy/paste it successfully.</violation>
</file>

<file name="skills/remotion-video-creation/rules/videos.md">

<violation number="1" location="skills/remotion-video-creation/rules/videos.md:41">
P2: The trimming section says `trimBefore`/`trimAfter` are in seconds, but the example (and the audio guide) treats them as frame counts (`2 * fps`). This inconsistency will mislead readers about the expected units.</violation>
</file>

<file name="skills/remotion-video-creation/SKILL.md">

<violation number="1" location="skills/remotion-video-creation/SKILL.md:16">
P2: These rule links point to files that don’t exist in the repo, so readers will hit broken links. Add the referenced rule files or update the links to the correct locations.</violation>
</file>

<file name="skills/autonomous-agent-harness/SKILL.md">

<violation number="1" location="skills/autonomous-agent-harness/SKILL.md:11">
P3: Use the standard skill section name “When to Use” so this skill follows the documented format and stays consistent with other skills.</violation>
</file>

<file name="skills/remotion-video-creation/rules/trimming.md">

<violation number="1" location="skills/remotion-video-creation/rules/trimming.md:17">
P2: `useVideoConfig()` returns a config object; assigning it directly to `fps` makes the arithmetic in this example evaluate to `NaN`. Destructure `fps` from the config like the other Remotion examples.</violation>
</file>

<file name="skills/remotion-video-creation/rules/extract-frames.md">

<violation number="1" location="skills/remotion-video-creation/rules/extract-frames.md:91">
P2: Abort inside the sample loop only breaks and resolves successfully, so callers can’t detect cancellation (the try/catch example will log completion even when aborted). Throw on abort in the loop to match the earlier abort checks and the documented behavior.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.


## Trimming

Use `trimBefore` and `trimAfter` to remove portions of the video. Values are in seconds.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The trimming section says trimBefore/trimAfter are in seconds, but the example (and the audio guide) treats them as frame counts (2 * fps). This inconsistency will mislead readers about the expected units.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At skills/remotion-video-creation/rules/videos.md, line 41:

<comment>The trimming section says `trimBefore`/`trimAfter` are in seconds, but the example (and the audio guide) treats them as frame counts (`2 * fps`). This inconsistency will mislead readers about the expected units.</comment>

<file context>
@@ -0,0 +1,171 @@
+
+## Trimming
+
+Use `trimBefore` and `trimAfter` to remove portions of the video. Values are in seconds.
+
+```tsx
</file context>
Suggested change
Use `trimBefore` and `trimAfter` to remove portions of the video. Values are in seconds.
Use `trimBefore` and `trimAfter` to remove portions of the video. Values are in frames.
Fix with Cubic


Read individual rule files for detailed explanations and code examples:

- [rules/3d.md](rules/3d.md) - 3D content in Remotion using Three.js and React Three Fiber
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: These rule links point to files that don’t exist in the repo, so readers will hit broken links. Add the referenced rule files or update the links to the correct locations.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At skills/remotion-video-creation/SKILL.md, line 16:

<comment>These rule links point to files that don’t exist in the repo, so readers will hit broken links. Add the referenced rule files or update the links to the correct locations.</comment>

<file context>
@@ -0,0 +1,43 @@
+
+Read individual rule files for detailed explanations and code examples:
+
+- [rules/3d.md](rules/3d.md) - 3D content in Remotion using Three.js and React Three Fiber
+- [rules/animations.md](rules/animations.md) - Fundamental animation skills for Remotion
+- [rules/assets.md](rules/assets.md) - Importing images, videos, audio, and fonts into Remotion
</file context>
Fix with Cubic

```tsx
import { Sequence, useVideoConfig } from "remotion";

const fps = useVideoConfig();
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: useVideoConfig() returns a config object; assigning it directly to fps makes the arithmetic in this example evaluate to NaN. Destructure fps from the config like the other Remotion examples.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At skills/remotion-video-creation/rules/trimming.md, line 17:

<comment>`useVideoConfig()` returns a config object; assigning it directly to `fps` makes the arithmetic in this example evaluate to `NaN`. Destructure `fps` from the config like the other Remotion examples.</comment>

<file context>
@@ -0,0 +1,53 @@
+```tsx
+import { Sequence, useVideoConfig } from "remotion";
+
+const fps = useVideoConfig();
+
+<Sequence from={-0.5 * fps}>
</file context>
Fix with Cubic


for await (using videoSample of sink.samplesAtTimestamps(timestamps)) {
if (signal?.aborted) {
break;
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Abort inside the sample loop only breaks and resolves successfully, so callers can’t detect cancellation (the try/catch example will log completion even when aborted). Throw on abort in the loop to match the earlier abort checks and the documented behavior.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At skills/remotion-video-creation/rules/extract-frames.md, line 91:

<comment>Abort inside the sample loop only breaks and resolves successfully, so callers can’t detect cancellation (the try/catch example will log completion even when aborted). Throw on abort in the loop to match the earlier abort checks and the documented behavior.</comment>

<file context>
@@ -0,0 +1,229 @@
+
+  for await (using videoSample of sink.samplesAtTimestamps(timestamps)) {
+    if (signal?.aborted) {
+      break;
+    }
+
</file context>
Fix with Cubic

Write animations in seconds and multiply them by the `fps` value from `useVideoConfig()`.

```tsx
import { useCurrentFrame } from "remotion";
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The example code uses useVideoConfig and interpolate without importing them, so the snippet won’t compile as written. Include the missing imports so readers can copy/paste it successfully.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At skills/remotion-video-creation/rules/animations.md, line 12:

<comment>The example code uses `useVideoConfig` and `interpolate` without importing them, so the snippet won’t compile as written. Include the missing imports so readers can copy/paste it successfully.</comment>

<file context>
@@ -0,0 +1,29 @@
+Write animations in seconds and multiply them by the `fps` value from `useVideoConfig()`.
+
+```tsx
+import { useCurrentFrame } from "remotion";
+
+export const FadeIn = () => {
</file context>
Fix with Cubic


Turn Claude Code into a persistent, self-directing agent system using only native features and MCP servers.

## When to Activate
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Use the standard skill section name “When to Use” so this skill follows the documented format and stays consistent with other skills.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At skills/autonomous-agent-harness/SKILL.md, line 11:

<comment>Use the standard skill section name “When to Use” so this skill follows the documented format and stays consistent with other skills.</comment>

<file context>
@@ -0,0 +1,267 @@
+
+Turn Claude Code into a persistent, self-directing agent system using only native features and MCP servers.
+
+## When to Activate
+
+- User wants an agent that runs continuously or on a schedule
</file context>
Fix with Cubic

…ript SHA

Critical:
- Pin all npx -y MCP server packages to specific versions in .mcp.json
  to prevent supply chain attacks via version hijacking:
  - @modelcontextprotocol/server-github@2025.4.8
  - @modelcontextprotocol/server-memory@2026.1.26
  - @modelcontextprotocol/server-sequential-thinking@2025.12.18
  - @playwright/mcp@0.0.69 (was 0.0.68)

Medium:
- Add .github/dependabot.yml for weekly npm + github-actions updates
  with grouped minor/patch PRs
- Pin actions/github-script to SHA (was @v7 tag, now pinned to commit)
@ecc-tools
Copy link
Copy Markdown
Contributor

ecc-tools bot commented Mar 31, 2026

Analyzing 5000 commits...

@ecc-tools
Copy link
Copy Markdown
Contributor

ecc-tools bot commented Mar 31, 2026

Analysis Failed

Not Found - https://docs.github.com/rest/git/refs#get-a-reference

Troubleshooting
Cause Resolution
Large repository Analysis may timeout on repos with extensive history
API rate limits Wait 15 minutes before retrying
Network issues Queue timeout is 15 minutes; retry may succeed
Permissions Verify app has Contents: Read access

Retry: /ecc-tools analyze


Report Issue | ECC Tools

New skill: social-graph-ranker
- Weighted social graph traversal with exponential decay across hops
- Bridge Score: B(m) = Σ w(t) · λ^(d(m,t)-1) ranks mutuals by target proximity
- Extended Score incorporates 2nd-order network (mutual-of-mutual connections)
- Final ranking includes engagement bonus for responsive connections
- Runs in parallel with lead-intelligence skill for combined warm+cold outreach
- Supports X API + LinkedIn CSV for graph harvesting
- Outputs tiered action list: warm intros, direct outreach, network gap analysis

Added to business-content install module. Catalog validates: 30/60/140.
@ecc-tools
Copy link
Copy Markdown
Contributor

ecc-tools bot commented Mar 31, 2026

Analyzing 5000 commits...

@ecc-tools
Copy link
Copy Markdown
Contributor

ecc-tools bot commented Mar 31, 2026

Analysis Failed

Not Found - https://docs.github.com/rest/git/refs#get-a-reference

Troubleshooting
Cause Resolution
Large repository Analysis may timeout on repos with extensive history
API rate limits Wait 15 minutes before retrying
Network issues Queue timeout is 15 minutes; retry may succeed
Permissions Verify app has Contents: Read access

Retry: /ecc-tools analyze


Report Issue | ECC Tools

Applied npm audit fix --force to resolve:
- minimatch ReDoS (3 vulnerabilities, HIGH)
- smol-toml DoS (MODERATE)
- brace-expansion memory exhaustion (MODERATE)
- markdownlint-cli upgraded from 0.47.0 to 0.48.0

npm audit now reports 0 vulnerabilities.
@ecc-tools
Copy link
Copy Markdown
Contributor

ecc-tools bot commented Mar 31, 2026

Analyzing 5000 commits...

@ecc-tools
Copy link
Copy Markdown
Contributor

ecc-tools bot commented Mar 31, 2026

Analysis Failed

Not Found - https://docs.github.com/rest/git/refs#get-a-reference

Troubleshooting
Cause Resolution
Large repository Analysis may timeout on repos with extensive history
API rate limits Wait 15 minutes before retrying
Network issues Queue timeout is 15 minutes; retry may succeed
Permissions Verify app has Contents: Read access

Retry: /ecc-tools analyze


Report Issue | ECC Tools

- MD047: ensure single trailing newline on all remotion rule files
- MD012: remove consecutive blank lines in lottie, measuring-dom-nodes, trimming
- MD034: wrap bare URLs in angle brackets (tailwind, transcribe-captions)
- yarn.lock: regenerated to sync with npm audit changes in package.json
@ecc-tools
Copy link
Copy Markdown
Contributor

ecc-tools bot commented Mar 31, 2026

Analyzing 5000 commits...

@ecc-tools
Copy link
Copy Markdown
Contributor

ecc-tools bot commented Mar 31, 2026

Analysis Failed

Not Found - https://docs.github.com/rest/git/refs#get-a-reference

Troubleshooting
Cause Resolution
Large repository Analysis may timeout on repos with extensive history
API rate limits Wait 15 minutes before retrying
Network issues Queue timeout is 15 minutes; retry may succeed
Permissions Verify app has Contents: Read access

Retry: /ecc-tools analyze


Report Issue | ECC Tools

@ecc-tools
Copy link
Copy Markdown
Contributor

ecc-tools bot commented Mar 31, 2026

Analyzing 5000 commits...

@ecc-tools
Copy link
Copy Markdown
Contributor

ecc-tools bot commented Mar 31, 2026

Analysis Failed

Not Found - https://docs.github.com/rest/git/refs#get-a-reference

Troubleshooting
Cause Resolution
Large repository Analysis may timeout on repos with extensive history
API rate limits Wait 15 minutes before retrying
Network issues Queue timeout is 15 minutes; retry may succeed
Permissions Verify app has Contents: Read access

Retry: /ecc-tools analyze


Report Issue | ECC Tools

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
skills/remotion-video-creation/rules/tailwind.md (1)

7-11: ⚠️ Potential issue | 🟠 Major

Add the required skill sections (When to Use, How It Works, Examples).

This skill document still lacks the required structural sections. As per coding guidelines, skills/**/*.md must include clear Markdown sections for When to Use, How It Works, and Examples.

📝 Proposed restructure
-You can and should use TailwindCSS in Remotion, if TailwindCSS is installed in the project.
-
-Don't use `transition-*` or `animate-*` classes - always animate using the `useCurrentFrame()` hook.  
-
-Tailwind must be installed and enabled first in a Remotion project - fetch  https://www.remotion.dev/docs/tailwind using WebFetch for instructions.
+## When to Use
+
+Use TailwindCSS in Remotion projects when Tailwind is already installed and enabled in the project.
+
+## How It Works
+
+- Tailwind must be installed and enabled first. Fetch https://www.remotion.dev/docs/tailwind using WebFetch for setup instructions.
+- Use Tailwind utility classes for styling.
+- **Do not** use `transition-*` or `animate-*` classes.
+- Always animate using Remotion's `useCurrentFrame()` hook instead.
+
+## Examples
+
+```tsx
+// ✅ Correct: Tailwind for styling, useCurrentFrame() for animation
+import { useCurrentFrame } from 'remotion';
+
+export const AnimatedBox = () => {
+  const frame = useCurrentFrame();
+  const opacity = Math.min(1, frame / 30);
+  
+  return (
+    <div 
+      className="w-64 h-64 bg-blue-500 rounded-lg"
+      style={{ opacity }}
+    >
+      Content
+    </div>
+  );
+};
+
+// ❌ Wrong: Using Tailwind animation classes
+<div className="animate-pulse bg-blue-500">Don't do this</div>
+```
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/remotion-video-creation/rules/tailwind.md` around lines 7 - 11, Add
the required Markdown sections "When to Use", "How It Works", and "Examples" to
skills/remotion-video-creation/rules/tailwind.md; in "When to Use" state that
Tailwind is suitable for styling in Remotion projects (only if Tailwind is
installed/enabled), in "How It Works" explain that animations must rely on
Remotion's useCurrentFrame() hook rather than Tailwind's transition-* or
animate-* classes, and in "Examples" include the proposed correct example
referencing the AnimatedBox component and useCurrentFrame() and a short "Don't
do this" note showing animate-* usage so readers see both the correct pattern
(useCurrentFrame → inline style opacity) and the incorrect pattern (Tailwind
animate-*).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@skills/lead-intelligence/SKILL.md`:
- Line 144: Update the phrase in the SKILL.md content where it currently reads
"GitHub: open source contributions (for developer-centric leads)" to use the
hyphenated compound adjective "open-source contributions" so it becomes "GitHub:
open-source contributions (for developer-centric leads)"; locate this exact
string and replace the unhyphenated form with the hyphenated form to improve
clarity.
- Around line 11-31: Rename the section headings to match the required skill
schema: change "When to Activate" to "When to Use", change "Pipeline Overview"
to "How It Works", and change any "Example Usage" or similar to "Examples"
(update the exact strings "When to Activate", "Pipeline Overview", and "Example
Usage"/"Example" wherever they appear in SKILL.md, including the referenced
later occurrence around line 210). Ensure the Tool Requirements and content
under Required/Optional remain unchanged and update any internal links or
references that point to the old headings so documentation and machine checks
keep working.

---

Duplicate comments:
In `@skills/remotion-video-creation/rules/tailwind.md`:
- Around line 7-11: Add the required Markdown sections "When to Use", "How It
Works", and "Examples" to skills/remotion-video-creation/rules/tailwind.md; in
"When to Use" state that Tailwind is suitable for styling in Remotion projects
(only if Tailwind is installed/enabled), in "How It Works" explain that
animations must rely on Remotion's useCurrentFrame() hook rather than Tailwind's
transition-* or animate-* classes, and in "Examples" include the proposed
correct example referencing the AnimatedBox component and useCurrentFrame() and
a short "Don't do this" note showing animate-* usage so readers see both the
correct pattern (useCurrentFrame → inline style opacity) and the incorrect
pattern (Tailwind animate-*).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 18c54fec-a51b-4d38-849e-1d98491da6bc

📥 Commits

Reviewing files that changed from the base of the PR and between 4723701 and cbc65a8.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (6)
  • skills/lead-intelligence/SKILL.md
  • skills/remotion-video-creation/rules/lottie.md
  • skills/remotion-video-creation/rules/measuring-dom-nodes.md
  • skills/remotion-video-creation/rules/tailwind.md
  • skills/remotion-video-creation/rules/transcribe-captions.md
  • skills/remotion-video-creation/rules/trimming.md
✅ Files skipped from review due to trivial changes (4)
  • skills/remotion-video-creation/rules/transcribe-captions.md
  • skills/remotion-video-creation/rules/lottie.md
  • skills/remotion-video-creation/rules/trimming.md
  • skills/remotion-video-creation/rules/measuring-dom-nodes.md

Comment on lines +11 to +31
## When to Activate

- User wants to find leads or prospects in a specific industry
- Building an outreach list for partnerships, sales, or fundraising
- Researching who to reach out to and the best path to reach them
- User says "find leads", "outreach list", "who should I reach out to", "warm intros"
- Needs to score or rank a list of contacts by relevance
- Wants to map mutual connections to find warm introduction paths

## Tool Requirements

### Required
- **Exa MCP** — Deep web search for people, companies, and signals (`web_search_exa`)
- **X API** — Follower/following graph, mutual analysis, recent activity (`X_BEARER_TOKEN`, `X_ACCESS_TOKEN`)

### Optional (enhance results)
- **LinkedIn** — Via browser-use MCP or direct API for connection graph
- **Apollo/Clay API** — For enrichment cross-reference if user has access
- **GitHub MCP** — For developer-centric lead qualification

## Pipeline Overview
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use the required skill section headings.

Please rename/add headings so the document explicitly contains “When to Use”, “How It Works”, and “Examples” (currently “When to Activate”, “Pipeline Overview”, and “Example Usage”). This keeps skill docs consistent and machine-checkable.

Suggested minimal heading update
-## When to Activate
+## When to Use
...
-## Pipeline Overview
+## How It Works
...
-## Example Usage
+## Examples

As per coding guidelines: “skills/**/*.md: Skill format must be Markdown with clear sections for When to Use, How It Works, and Examples”.

Also applies to: 210-210

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lead-intelligence/SKILL.md` around lines 11 - 31, Rename the section
headings to match the required skill schema: change "When to Activate" to "When
to Use", change "Pipeline Overview" to "How It Works", and change any "Example
Usage" or similar to "Examples" (update the exact strings "When to Activate",
"Pipeline Overview", and "Example Usage"/"Example" wherever they appear in
SKILL.md, including the referenced later occurrence around line 210). Ensure the
Tool Requirements and content under Required/Optional remain unchanged and
update any internal links or references that point to the old headings so
documentation and machine checks keep working.

### Enrichment Sources
- Exa: company data, news, blog posts
- X API: recent tweets, bio, followers
- GitHub: open source contributions (for developer-centric leads)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Hyphenate compound adjective for clarity.

At Line 144, use “open-source contributions” instead of “open source contributions”.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~144-~144: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...recent tweets, bio, followers - GitHub: open source contributions (for developer-centric le...

(EN_COMPOUND_ADJECTIVE_INTERNAL)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lead-intelligence/SKILL.md` at line 144, Update the phrase in the
SKILL.md content where it currently reads "GitHub: open source contributions
(for developer-centric leads)" to use the hyphenated compound adjective
"open-source contributions" so it becomes "GitHub: open-source contributions
(for developer-centric leads)"; locate this exact string and replace the
unhyphenated form with the hyphenated form to improve clarity.

@affaan-m affaan-m merged commit 6cc85ef into main Mar 31, 2026
38 of 40 checks passed
@affaan-m affaan-m mentioned this pull request Mar 31, 2026
19 tasks
@affaan-m affaan-m deleted the fix/ci-test-failures branch March 31, 2026 22:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant